﻿using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Xml;
using System.IO;
using System.Reflection;
using System.Text.Unicode;

namespace Tnelab.MBWrapper
{
    internal static class MBWke
    {
        /// <summary>
        /// 把node.dll展开到程序当前目录
        /// </summary>
        static MBWke()
        {            
            if (!File.Exists(Path.Combine(Environment.CurrentDirectory,"node.dll")))
            {
                using (var stream = Assembly.GetAssembly(typeof(MBWke)).GetManifestResourceStream("Tnelab.MBWrapper.node.dll"))
                {
                    using (var outStream = File.Create("node.dll"))
                    {
                        stream.CopyTo(outStream);
                    }
                }
            }
            wkeInit();
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct wkeRect
        {
            public int x;
            public int y;
            public int w;
            public int h;
        }
        [StructLayout(LayoutKind.Sequential)]
        internal struct jsData
        {
            [MarshalAs(UnmanagedType.ByValArray,SizeConst = 100)]
            public char[] typeName;
            public jsGetPropertyCallback propertyGet;
            public jsSetPropertyCallback propertySet;
            public jsFinalizeCallback finalize;
            public jsCallAsFunctionCallback callAsFunction;
        }
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        internal unsafe delegate void wkePaintBitUpdatedCallback(IntPtr webView, IntPtr param, IntPtr buffer, wkeRect* r, int width, int height);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        [return:MarshalAs(UnmanagedType.Bool)]
        internal delegate bool wkeLoadUrlBeginCallback(IntPtr webView, IntPtr param, [MarshalAs(UnmanagedType.LPUTF8Str)]string url, IntPtr job);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        internal unsafe delegate void wkeDocumentReadyCallback(IntPtr webView, IntPtr param);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        internal delegate void wkeLoadUrlEndCallback(IntPtr webView, IntPtr param, [MarshalAs(UnmanagedType.LPUTF8Str)]string url, IntPtr job, IntPtr buf, int len);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        internal delegate Int64 wkeJsNativeFunction(IntPtr es, IntPtr param);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        internal delegate Int64 jsGetPropertyCallback(IntPtr es, Int64 theObject, [MarshalAs(UnmanagedType.LPStr)]string propertyName);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        [return:MarshalAs(UnmanagedType.Bool)]
        internal delegate bool jsSetPropertyCallback(IntPtr es, Int64 theObject, [MarshalAs(UnmanagedType.LPStr)] string propertyName, Int64 value);
        [return: MarshalAs(UnmanagedType.Bool)]
        internal delegate Int64 jsCallAsFunctionCallback(IntPtr es, Int64 theObject, Int64[] args, int argCount);
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        internal delegate void jsFinalizeCallback(IntPtr data);

        const string node_dll_name = "node";
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public static extern void wkeInit();
        [DllImport(node_dll_name,CallingConvention =CallingConvention.Cdecl)]
        public static extern IntPtr wkeCreateWebView();
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        [return:MarshalAs(UnmanagedType.Bool)]
        public static extern bool wkeIsTransparent(IntPtr webView);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public static extern void wkeSetTransparent(IntPtr wkeWebView,bool transparent);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        public static extern void wkeLoadURLW(IntPtr wkeWebView, string url);
        [DllImport(node_dll_name,CallingConvention =CallingConvention.Cdecl)]
        public static extern void wkeOnPaintBitUpdated(IntPtr webView, wkePaintBitUpdatedCallback callback, IntPtr callbackParam);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public static extern void wkeResize(IntPtr webView, int w, int h);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public static extern void wkeOnLoadUrlBegin(IntPtr webView, wkeLoadUrlBeginCallback callback, IntPtr callbackParam);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public static extern void wkePaint(IntPtr webView, IntPtr bits, int pitch);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public static extern void wkeOnDocumentReady(IntPtr webView, wkeDocumentReadyCallback callback, IntPtr param);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public static extern void wkeRunMessageLoop();
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public static extern void wkeSetHandle(IntPtr webView, IntPtr wnd);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public static extern int wkeGetWidth(IntPtr webView);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public static extern int wkeGetHeight(IntPtr webView);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool wkeFireKeyDownEvent(IntPtr webView, uint virtualKeyCode, uint flags, bool systemKey);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool wkeFireKeyUpEvent(IntPtr webView, uint virtualKeyCode, uint flags, bool systemKey);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public static extern void wkeSetFocus(IntPtr webView);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public static extern void wkeKillFocus(IntPtr webView);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool wkeFireKeyPressEvent(IntPtr webView, uint virtualKeyCode, uint flags, bool systemKey);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool wkeFireMouseWheelEvent(IntPtr webView, int x, int y, int delta, uint flags);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool wkeFireMouseEvent(IntPtr webView, uint message, int x, int y, uint flags);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public static extern int wkeGetCursorInfoType(IntPtr webView);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl,CharSet =CharSet.Unicode)]
        public static extern Int64 wkeRunJSW(IntPtr webView, string script);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr wkeGlobalExec(IntPtr webView);
        [DllImport(node_dll_name,CharSet =CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr jsToStringW(IntPtr es, Int64 v);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl,CharSet =CharSet.Ansi)]
        public extern static void wkeJsBindFunction(string name, wkeJsNativeFunction fn, IntPtr param, uint argCount);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public extern static Int64 jsUndefined();
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public extern static Int64 jsArg(IntPtr es, int argIdx);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public extern static int jsToInt(IntPtr es, Int64 v);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        public extern static void jsSetGlobal(IntPtr es, string prop, Int64 v);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public extern static IntPtr jsGetWebView(IntPtr es);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public extern static void wkeDestroyWebView(IntPtr webView);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl,CharSet =CharSet.Ansi)]
        public extern static Int64 jsGetGlobal(IntPtr es, string prop);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public extern static Int64 jsCall(IntPtr es, Int64 func, Int64 thisObject, Int64[] args, int argCount);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        public extern static void jsDeleteObjectProp(IntPtr es, Int64 theObject, string prop);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public extern static Int64 jsInt(int n);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
        public extern static Int64 jsStringW(IntPtr es, string str);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public extern static Int64 jsObject(IntPtr es, ref jsData obj);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        public extern static Int64 jsGet(IntPtr es, Int64 theObject, string prop);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public extern static void wkeNetHookRequest(IntPtr jobPtr);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public extern static void wkeOnLoadUrlEnd(IntPtr webView, wkeLoadUrlEndCallback callback, IntPtr callbackParam);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl)]
        public extern static void wkeNetSetData(IntPtr jobPtr, IntPtr buf, int len);
        [DllImport(node_dll_name, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        public extern static void wkeSetDebugConfig(IntPtr webView, string debugString, [MarshalAs(UnmanagedType.LPUTF8Str)]string param);
    }
}
